; Published under the MIT License

; Copyright(c) 2010 Ajtaji and Zenner

; Permission is hereby granted, free of charge, To any person obtaining a copy
; of this software And associated documentation files(the "Software"), To deal
; in the Software without restriction, including without limitation the rights
; To use, copy, modify, merge, publish, distribute, sublicense, And/Or sell
; copies of the Software, And To permit persons To whom the Software is
; furnished To do so, subject To the following conditions :

; The above copyright notice And this permission notice shall be included in
; all copies Or substantial portions of the Software.

; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS Or
; IMPLIED, INCLUDING BUT Not LIMITED To THE WARRANTIES OF MERCHANTABILITY,
; FITNESS For A PARTICULAR PURPOSE And NONINFRINGEMENT.IN NO EVENT SHALL THE
; AUTHORS Or COPYRIGHT HOLDERS BE LIABLE For ANY CLAIM, DAMAGES Or OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT Or OTHERWISE, ARISING FROM,
; OUT OF Or IN CONNECTION With THE SOFTWARE Or THE USE Or OTHER DEALINGS IN
; THE SOFTWARE.





;Section for standard constants, structures, macros and declaration
UsePNGImageDecoder()
UseTGAImageDecoder()
UseJPEGImageDecoder()


;Declare
;wingdi.h constants
#DM_BITSPERPEL = $40000
#DM_PELSWIDTH = $80000
#DM_PELSHEIGHT = $100000

;winuser.h constants
; #ENUM_CURRENT_SETTINGS = -1
; #CDS_TEST = 2
; #CDS_FULLSCREEN = 4
; #CDS_RESET = $40000000
; #DISP_CHANGE_SUCCESSFUL = 0
; #SC_MONITORPOWER = $F170


Macro loword(value)
  (value & $ffff)
EndMacro

Macro hiword(value)
  ((value>>16) & $ffff)
EndMacro

;CompilerIf #Directory
  XIncludeFile "..\openglengine\OpenGL1_5.pbi" ;include the gl.h constant
  XIncludeFile "..\openglengine\FastImageRoutines.pb"
; CompilerElse
;   XIncludeFile "OpenGL1_5.pbi" ;include the gl.h constant
;   XIncludeFile "FastImageRoutines.pb"
; CompilerEndIf




;Declare.l NEXTPOWEROF2(number.l)
Declare.l WndProc(hWnd.l,uMsg.l,wParam.l,lParam.l) ;Declaration For WndProc
Procedure glEnable2D()
  
  gldisable(#GL_DEPTH_TEST)
  glGetIntegerv(#GL_VIEWPORT,@vport(0));
  glMatrixMode(#GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  glOrtho(0, vPort(2),vPort(3), 0,  -1, 1);
  glMatrixMode(#GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();
  status2d=#True
  ProcedureReturn
  
EndProcedure

Procedure glDisable2D()
  glenable(#GL_DEPTH_TEST)
  glMatrixMode(#GL_PROJECTION);
  glPopMatrix();
  glMatrixMode(#GL_MODELVIEW);
  glPopMatrix();
  status2d=#False
  ProcedureReturn
EndProcedure

Procedure ReSizeGLScene(width.l,height.l) ;Resize And Initialize The GL Window
  width=GlWindow\x
  height=Glwindow\y
  swidth=width ;set screen width and height globals
  sheight=height
  If height=0 : height=1 : EndIf ;Prevent A Divide By Zero Error
  
  glViewport(0,0,width,height) ;Reset The Current Viewport
  
  glMatrixMode(#GL_PROJECTION) ;Select The Projection Matrix
  glLoadIdentity() ;Reset The Projection Matrix
  
  gluPerspective(45.0,width/height,0.1,1700.0) ;Calculate The Aspect Ratio Of The Window
  
  glMatrixMode(#GL_MODELVIEW) ;Select The Modelview Matrix
  glLoadIdentity() ;Reset The Modelview Matrix
  ;Debug status2d
;   If status2d=#True
     glenable2d()
;      glMatrixMode(#GL_PROJECTION);
;      glLoadIdentity();
;      glOrtho(0, width, height, 0, -1, 1);
;      glMatrixMode(#GL_MODELVIEW);
;      glLoadIdentity();
   glDisable2d() 
  ;EndIf 
EndProcedure

Procedure.l WndProc(hWnd.l,uMsg.l,wParam.l,lParam.l)

 Select uMsg ;Check For Windows Messages
 
  Case #WM_ACTIVATE ;Watch For Window Activate Message
   If HiWord(wParam)=0 ;Check Minimization State
    active=#True ;Program Is Active
   Else
    active=#False ;Program Is No Longer Active
   EndIf
   ProcedureReturn 0 ;Return To The Message Loop
   
  Case #WM_SYSCOMMAND ;Intercept System Commands
   Select wParam ;Check System Calls
    Case #SC_SCREENSAVE ;Screensaver Trying To Start?
     ProcedureReturn 0 ;Prevent From Happening
    Case #SC_MONITORPOWER ;Monitor Trying To Enter Powersave?
     ProcedureReturn 0 ;Prevent From Happening
   EndSelect
   
  Case #WM_CLOSE ;Did We Receive A Close Message?
   PostQuitMessage_(0) ;Send A Quit Message
   ProcedureReturn 0 ;Jump Back
   
  Case #WM_KEYDOWN ;Is A Key Being Held Down?
   keys(wParam)=#True ;If So, Mark It As TRUE
   ProcedureReturn 0 ;Jump Back
   
  Case #WM_KEYUP ;Has A Key Been Released?
   keys(wParam)=#False ;If So, Mark It As FALSE
   ProcedureReturn 0 ;Jump Back
   
  Case #WM_SIZE ;Resize The OpenGL Window
   ReSizeGLScene(LoWord(lParam),HiWord(lParam)) ;LoWord=Width, HiWord=Height
   ProcedureReturn 0 ;Jump Back
   
 EndSelect
 
 ;Pass All Unhandled Messages To DefWindowProc
 ProcedureReturn DefWindowProc_(hWnd,uMsg,wParam,lParam)
 
EndProcedure

Procedure NEXTPOWEROF2(number.l)
  EnableASM
  ;number=40
  
  Protected RetVal.l = 1;
  
  XOr ecx , ecx
  BSR ecx , Number
  INC ecx
  SHL RetVal , cl
  DisableASM
  ProcedureReturn RetVal.l
  
EndProcedure
Procedure GLError(String.s)
  
  MessageRequester("GlError",string)
  Debug string
  EndProcedure


Procedure CreateImageList(Number)
  Protected ImageList = glGenLists(1)
  glNewList(ImageList,#GL_COMPILE);
  glBegin(#GL_QUADS)
  glTexCoord2f(0, 0): glVertex2f(0, 0) ;    Bottom Left Of The Texture And Quad
  glTexCoord2f(0, imageheight/newimageheight): glVertex2f(0, imageheight);     Top Left Of The Texture And Quad
  glTexCoord2f(imagewidth/newimagewidth,  imageheight/newimageheight): glVertex2f( imagewidth,  imageheight);     Top Right Of The Texture And Quad
  glTexCoord2f(imagewidth/newimagewidth, 0): glVertex2f(imagewidth, 0);     Bottom Right Of The Texture And Quad
  glEnd()
  glEndList()
  
  ProcedureReturn ImageList
EndProcedure

Procedure glDrawSprite(number,x,y,z=0)
  glLoadIdentity() ;Reset The Current Matrix
  glbindtexture(#GL_TEXTURE_2D,sprite(number)\image)
  glTranslated(x,y,z) ;Translate Units Into The Screen Position
  glRotatef(sprite(number)\rotation,0.0,0.0,1.0) ;Rotate sprite if needed
  glcalllist(sprite(number)\imagelist)
  
EndProcedure


Procedure.l LoadGLSpriteTexture(TextureNumber.l,filename.s,Location=0) ;Load Images And Convert To Texture
  
  If location=0
    
    If LoadImage(texturenumber,filename)
    Else
    glerror(filename+" Not Found!")
    EndIf
    
  Else
  
    Debug texturenumber
    CatchImage(texturenumber,location)
    
  EndIf
  
  imageWidth=ImageWidth(texturenumber)
  imageHeight=ImageHeight(texturenumber)
  
  mem=AllocateMemory((imageWidth*imageHeight) << 2) ;Allocate system memory for Dib(Bitmap)
  CopyImageToMemory(textureNumber,mem);Copy purebasic image object to memory
  FreeImage(texturenumber)
  n=imagewidth
  If -(~(n&(n-1)))<>#True
    NewImageWidth=NextPowerOf2(n)
  Else
    NewImageWidth=n
  EndIf
  
  n=imageheight
  If -(~(n&(n-1)))<>#True
    NewImageHeight=NextPowerOf2(n)
  Else
    NewImageHeight=n
  EndIf
  
  newimage=CreateImage(#PB_Any,newimagewidth,newimageheight,32)
  
  ;   imageWidth=ImageWidth(texturenumber)
  ;   imageHeight=ImageHeight(texturenumber)
  
  newmem=AllocateMemory((newimageWidth*newimageHeight) << 2) ;Allocate system memory for Dib(Bitmap)
  RtlFillMemory_(newmem, (newimageWidth*newimageHeight) << 2, $00)
  CopyImageToMemory(newimage,newmem);Copy purebasic image object to memory
  FreeImage(newimage)
  ;*****************************************************************************************
  ;SWAP THE RED AND BLUE VALUES TO CONVERT FROM BGR TO RGB BITMAP
  ;WINDOWS USES BGR FORMAT=GAY
  ;*****************************************************************************************
  MemorySize = ((imageWidth*imageHeight) << 2);Caculate how many bytes the image use
  ;Grab the blue Value from the BGR Bitmap
  keyred=fastred(glcolorkey)
  keygreen=fastgreen(glcolorkey)
  keyblue=fastblue(glcolorkey)
  For y=0 To imageHeight - 1 ;Step (newimageheight<<2)
    For x = 0 To ImageWidth*4 - 1 Step 4;Loop through the pixels of the image
      
      glColor.l = PeekL(mem + (x+(y*imagewidth<<2)));Grab a Pixel from the image
      
      red=fastred(glcolor);Grab the red value from the BGR bitmap
      green=fastgreen(glcolor);Grab the Green Value from the BGR bitmap
      blue=fastblue(glcolor)
      
      
      If red=keyred And green=keygreen And blue=keyblue
        ;Debug color
        PokeL(newmem + (x+(y*(newimagewidth<<2))),MyRGBA(0,0,0,0)); Swap the Blue and Red Channel for the pixel
      Else
        PokeL(newmem + (x+(y*(newimagewidth<<2))),MyRGBA(red,green,blue,255)); Swap the Blue and Red Channel for the pixel  
      EndIf
      
    Next x
  Next y
  FreeMemory(mem)  
  ;******************************************************************************************
  ;-(~(n&(n-1)))  Equation for ispowerof2
  ;******************************************************************************************  

 glGenTextures_(1,@gltexture(TextureNumber)) ;Create The Texture Numerical name
  type=#gl_rgba;Which image type stored in memory
 
 ;*****************************************************************************************
 ;Typical Texture Generation Using Data From The Bitmap
 ;Create Texture
 ;*****************************************************************************************
 bits=newmem;Image bytes location
 
 glBindTexture_(#GL_TEXTURE_2D,gltexture(TextureNumber.l)) ;2d texture (x and y size)
 glTexParameteri_(#GL_TEXTURE_2D,#GL_TEXTURE_MAG_FILTER,#GL_linear) ;Scale linearly when image bigger than texture
 glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_linear) ;Scale linearly when image smaller than texture
 glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_repeat)
 glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_repeat)
 ;2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
 ;border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
 glTexImage2D_(#GL_TEXTURE_2D,0,type,newimagewidth,newimageheight,0,type ,#GL_UNSIGNED_BYTE,bits);GL_BGR_EXT
 
 
 
 ;If *hBMP(TextureNumber.l) ;If Texture Exists
 FreeMemory(newmem) ;Free The DIB
 ;EndIf
 ProcedureReturn gltexture(TextureNumber)
EndProcedure
;******************************************************************************************

Procedure.l GlCatchSprite(number,location,dummy)
  ;bits=*hBMP(TextureNumber.l)+*hBMP(TextureNumber.l)\biSize+(*hBMP(TextureNumber.l)\biClrUsed*4) ;Get the bits
  
  sprite(number)\image=LoadGLSpriteTexture(number,"DummyString",location)
  sprite(number)\imagelist=createimagelist(number)
EndProcedure
Procedure GlLoadSprite(number,file.s)
  sprite(number)\image=LoadGLSpriteTexture(number,file)
  sprite(number)\imagelist=createimagelist(number)
EndProcedure


;******************************************************************************************


Procedure InitVars()


EndProcedure

Procedure.l InitGL() ;All Setup For OpenGL Goes Here
  
  ;  Protected df.f=100 ;Material Shininess
  ;
  ;  glClearDepth(1.0) ;Depth Buffer Setup
  ;  glEnable_(#GL_DEPTH_TEST) ;Enables Depth Testing
  ;  glDepthFunc_(#GL_LEQUAL) ;The Type Of Depth Testing To Do
  ;  glHint_(#GL_PERSPECTIVE_CORRECTION_HINT,#GL_NICEST) ;Really Nice Perspective Calculations
  ;
  ;  glClearColor_(0.0,0.0,0.0,0.0) ;Black Background
  ;  glMatrixMode_(#GL_MODELVIEW) ;Select The Modelview Matrix
  ;  glLoadIdentity_() ;Reset The Modelview Matrix
  ;
  ;  glShadeModel_(#GL_SMOOTH) ;Enable Smooth Shading
  ;  glEnable_(#GL_CULL_FACE) ;Enable Culling
  ;  glEnable_(#GL_DEPTH_TEST) ;Enable Depth Testing
  ;
  ;  ;glMaterialfv_(#GL_FRONT,#GL_SPECULAR,spec()) ;Set Material Specular
  ;  glMaterialfv_(#GL_FRONT,#GL_SHININESS,@df) ;Set Material Shininess
  ;
  ;  glEnable_(#GL_LIGHTING) ;Enable Lighting
  ;glLightfv_(#GL_LIGHT0,#GL_POSITION,posl()) ;Position The Light
  ;glLightfv_(#GL_LIGHT0,#GL_AMBIENT,amb2()) ;Setup The Ambient Light
  ;glEnable_(#GL_LIGHT0) ;Enable Light One
  ;
  ;glLightModelfv_(#GL_LIGHT_MODEL_AMBIENT,amb()) ;Ambient Model Lighting
  ;glEnable_(#GL_COLOR_MATERIAL) ;Enable Material Coloring
  ;glColorMaterial_(#GL_FRONT, #GL_AMBIENT_AND_DIFFUSE)
  ;
  ;  glEnable_(#GL_BLEND) ;Enable Blending
  ;  glBlendFunc_(#GL_SRC_ALPHA,#GL_ONE) ;Select The Type Of Blending
  ;
  ;  ;glEnable_(#GL_TEXTURE_2D) ;Enable Texture Mapping
  ;  ;LoadGLTextures()
  ;glClearDepth(1.0) : ;` Enables Clearing Of The Depth Buffer
  ;glDepthFunc(#gl_lequal) : ;` The Type Of Depth Test To Do
  ;glBlendFunc(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA)                :;` Select The Type Of Blending
  ;glShadeModel(#GL_SMOOTH) : ;` Enables Smooth Color Shading
  ;glEnable(#GL_Normalize)
  ;glEnable(#GL_Cull_Face)
  ;glEnable(#GL_COLOR_MATERIAL)
  ;glenable(#GL_DEPTH_TEST)
  ;glEnable(#GL_LIGHTING)
  ;gldisable(#GL_LIGHTING)
  ;glHint(#GL_PERSPECTIVE_CORRECTION_HINT, #GL_NICEST);:`
  glAlphaFunc(#GL_greater, 0.666);
  glenable(#GL_ALPHA_TEST);
  glEnable(#GL_TEXTURE_2D)
  ;glTexEnvi(#GL_TEXTURE_ENV, #GL_TEXTURE_ENV_MODE, #GL_REPLACE)
  ProcedureReturn #True ;Initialization Went OK
  
EndProcedure

Procedure.l DrawGLScene() ;Here's Where We Do All The Drawing Not :p
  
  
  
EndProcedure

Procedure KillGLWindow() ;Properly Kill The Window (not really), good enough

 If fullscreen ;Are We In Fullscreen Mode?
  If ChangeDisplaySettings_(#Null,#CDS_TEST)=0 ;If The Shortcut Doesn't Work
   ChangeDisplaySettings_(#Null,#CDS_RESET) ;Do It Anyway (To Get The Values Out Of The Registry)
   ChangeDisplaySettings_(DMsaved,#CDS_RESET) ;Change It To The Saved Settings
  Else
   ChangeDisplaySettings_(#Null,#CDS_RESET) ;If It Works, Go Right Ahead
  EndIf
  ShowCursor_(#True) ;Show Mouse Pointer
 EndIf
 
 If hRC ;Do We Have A Rendering Context?
  If wglMakeCurrent_(#Null,#Null)=0 ;Are We Able To Release The DC And RC Contexts?
   MessageBox_(#Null,"Release Of DC And RC Failed.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
  EndIf
  If wglDeleteContext_(hRC)=0 ;Are We Able To Delete The RC?
   MessageBox_(#Null,"Release Rendering Context Failed.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
  EndIf
  hRC=#Null ;Set RC To NULL
 EndIf
 
 If hDC And ReleaseDC_(hWnd,hDC)=0 ;Are We Able To Release The DC
  MessageBox_(#Null,"Release Device Context Failed.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
  hDC=#Null ;Set DC To NULL
 EndIf
  
EndProcedure

;This Code Creates Our OpenGL Window. Parameters Are:
;title - Title To Appear At The Top Of The Window
;width - Width Of The GL Window Or Fullscreen Mode
;height - Height Of The GL Window Or Fullscreen Mode
;bits - Number Of Bits To Use For Color (8/16/24/32)
;fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE)

Procedure CreateGLWindow(*fullscreenflag.b)
  title.s=GlWindow\name
  width.l=GlWindow\x
  height.l=GlWindow\y
  bits.l=GlWindow\bits
  FullScreen=GlWindow\Fullscreen
  Global hInstance
  Global Hwnd
  Global hDC
  Global hRC
  Protected PixelFormat.l ;Holds The Results After Searching For A Match
  Protected wc.WNDCLASS ;Windows Class Structure
  Protected dwExStyle.l ;Window Extended Style
  Protected dwStyle.l ;Window Style
  Protected WindowRect.RECT ;Grabs Rectangle Upper Left / Lower Right Values
  Protected wpos.POINT ;Window position
  
  WindowRect\left=0 ;Set Left Value To 0
  WindowRect\right=width ;Set Right Value To Requested Width
  WindowRect\top=0 ;Set Top Value To 0
  WindowRect\bottom=height ;Set Bottom Value To Requested Height
  
  ;fullscreen=1;fullscreenflag ;Set The Global Fullscreen Flag
  
  hInstance=GetModuleHandle_(#Null) ;Grab An Instance For Our Window
 
  wc\style=#CS_HREDRAW | #CS_VREDRAW | #CS_OWNDC ;Redraw On Size, And Own DC For Window
  wc\lpfnWndProc=@WndProc() ;WndProc Handles Messages
  wc\cbClsExtra=0 ;No Extra Window Data
  wc\cbWndExtra=0 ;No Extra Window Data
  wc\hInstance=hInstance ;Set The Instance
  wc\hIcon=LoadIcon_(#Null,#IDI_WINLOGO) ;Load The Default Icon
  wc\hCursor=LoadCursor_(#Null,#IDC_ARROW) ;Load The Arrow Pointer
  wc\hbrBackground=#Null ;No Background Required For GL
  wc\lpszMenuName=#Null ;We Don't Want A Menu
  wc\lpszClassName=@"OpenGL" ;Set The Class Name 
  
  If Not wcRegistered       ;put in to tell if class has been registered already.  application only needs to do this once.
    If RegisterClass_(wc)=0 ;Attempt To Register The Window Class
      MessageBox_(#Null,"Failed To Register The Window Class.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
      ProcedureReturn #False
    Else
      wcRegistered = #True
    EndIf
  EndIf  
  
  EnumDisplaySettings_(#Null,#ENUM_CURRENT_SETTINGS,DMsaved) ;Save The Current Display State
  
  If fullscreen ;Attempt Fullscreen Mode?
    Protected dmScreenSettings.DEVMODE ;Device Mode
    dmScreenSettings\dmSize=SizeOf(DEVMODE) ;Size Of The Devmode Structure
    dmScreenSettings\dmFields=#DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT ;bit flags to specify the members of DEVMODE that were initialized
    dmScreenSettings\dmBitsPerPel=bits ;Selected Bits Per Pixel
    dmScreenSettings\dmPelsWidth=width ;Selected Screen Width in pixels
    dmScreenSettings\dmPelsHeight=height ;Selected Screen Height in pixels
    
    ;Try To Set Selected Mode And Get Results. Note: CDS_FULLSCREEN Gets Rid Of Start Bar
    If ChangeDisplaySettings_(dmScreenSettings,#CDS_FULLSCREEN)<>#DISP_CHANGE_SUCCESSFUL
      ;If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode
      If MessageBox_(#Null,"The Requested Fullscreen Mode Is Not Supported By"+Chr(10)+"Your Video Card. Use Windowed Mode Instead?","NeHe GL",#MB_YESNO | #MB_ICONEXCLAMATION)=#IDYES
        fullscreen=#False ;Windowed Mode Selected.  Fullscreen = FALSE
      Else
        ;Pop Up A Message Box Letting User Know The Program Is Closing
        MessageBox_(#Null,"Program Will Now Close.","ERROR",#MB_OK | #MB_ICONSTOP)
        ProcedureReturn #False
      EndIf
    EndIf
  EndIf
  
  If fullscreen ;Are We Still In Fullscreen Mode?
  dwExStyle=#WS_EX_APPWINDOW ;Window Extended Style
  dwStyle=#WS_POPUP ;Windows Style
  ShowCursor_(#False) ;Hide Mouse Pointer
  Else
  dwExStyle=#WS_EX_APPWINDOW | #WS_EX_WINDOWEDGE ;Window Extended Style
  dwStyle=#WS_OVERLAPPEDWINDOW ;Windows Style
  EndIf
  
  AdjustWindowRectEx_(WindowRect,dwStyle,#False,dwExStyle) ;Adjust Window To True Requested Size
  
  If fullscreen=0 ;if not fullscreen mode calculate screen centered window
    wpos\x=(GetSystemMetrics_(#SM_CXSCREEN)/2)-((WindowRect\right-WindowRect\left)/2)
    wpos\y=(GetSystemMetrics_(#SM_CYSCREEN)/2)-((WindowRect\bottom-WindowRect\top)/2)
  EndIf
  
  ;CreateWindowEx_(Extended Window Style, Class Name, Window Title, Window Style, Window X Position, Window Y Position, Width, Height, No Parent Window, No Menu, Instance, No Creation Data)
  hWnd=CreateWindowEx_(dwExStyle,"OpenGL",title,dwStyle | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN,wpos\x,wpos\y,WindowRect\right-WindowRect\left,WindowRect\bottom-WindowRect\top,#Null,#Null,hInstance,#Null)
  If hWnd=0
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Window Creation Error.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
  EndIf
  Global WindowCreated=#True
 

 Repeat
  If PeekMessage_(msg,#Null,0,0,#PM_REMOVE) ;Is There A Message Waiting?
  
   If msg\message=#WM_QUIT ;Have We Received A Quit Message?
     done=#True ;If So done=TRUE
   Else ;If Not, Deal With Window Message
     TranslateMessage_(msg) ;Translate The Message
     DispatchMessage_(msg) ;Dispatch The Message
   EndIf
   
 Else ;If There Are No Message
   

   If keys(#VK_ESCAPE) ;Active?  Was There A Quit Received?
     
     done=#True ;ESC or DrawGLScene Signalled A Quit
    
   EndIf
   


 EndIf
 Sleep_(1)
 
 ForEver 
 ProcedureReturn #True ;Success
 
EndProcedure

Procedure GetWindowGoodies()
 Protected pfd.PIXELFORMATDESCRIPTOR ;pfd Tells Windows How We Want Things To Be
 pfd\nSize=SizeOf(PIXELFORMATDESCRIPTOR) ;Size Of This Structure
 pfd\nVersion=1 ;Version Number
 pfd\dwFlags=#PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW ;Format Must Support Window, OpenGL, Double Buffering
 pfd\iPixelType=#PFD_TYPE_RGBA ;Request An RGBA Format
 pfd\cColorBits=bits ;Select Our Color Depth
 pfd\cRedBits=0 ;Color Bits Ignored
 pfd\cRedShift=0
 pfd\cGreenBits=0
 pfd\cGreenShift=0
 pfd\cBlueBits=0
 pfd\cBlueShift=0
 pfd\cAlphaBits=0 ;No Alpha Buffer
 pfd\cAlphaShift=0 ;Shift Bit Ignored
 pfd\cAccumBits=0 ;No Accumulation Buffer
 pfd\cAccumRedBits=0 ;Accumulation Bits Ignored
 pfd\cAccumGreenBits=0
 pfd\cAccumBlueBits=0
 pfd\cAccumAlphaBits=0
 pfd\cDepthBits=32 ;16Bit Z-Buffer (Depth Buffer)
 pfd\cStencilBits=0 ;No Stencil Buffer
 pfd\cAuxBuffers=0 ;No Auxiliary Buffer
 pfd\iLayerType=#PFD_MAIN_PLANE ;Main Drawing Layer
 pfd\bReserved=0 ;Reserved
 pfd\dwLayerMask=0 ;Layer Masks Ignored
 pfd\dwVisibleMask=0
 pfd\dwDamageMask=0
 
 hDC=GetDC_(hWnd)
 If hDC=0 ;Did We Get A Device Context?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Create A GL Device Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 PixelFormat=ChoosePixelFormat_(hDC,pfd)
 If PixelFormat=0 ;Did Windows Find A Matching Pixel Format?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Find A Suitable PixelFormat.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 If SetPixelFormat_(hDC,PixelFormat,pfd)=0 ;Are We Able To Set The Pixel Format?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Set The PixelFormat.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 hRC=wglCreateContext_(hDC)
 If hRC=0 ;Are We Able To Get A Rendering Context?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Create A GL Rendering Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 If wglMakeCurrent_(hDC,hRC)=0 ;Try To Activate The Rendering Context
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Activate The GL Rendering Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 ShowWindow_(hWnd,#SW_SHOW) ;Show The Window
 SetForegroundWindow_(hWnd) ;Slightly Higher Priority
 SetFocus_(hWnd) ;Sets Keyboard Focus To The Window
 ReSizeGLScene(width,height) ;Set Up Our Perspective GL Screen
 
 If InitGL()=0 ;Initialize Our Newly Created GL Window
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Initialization Failed.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
  
  EndProcedure

  Procedure ProcessKeys() ;Process Key Presses
    
 
;  If keys(#VK_F1) ;Is F1 Being Pressed?
;   keys(#VK_F1)=#False ;If So Make Key FALSE
;   KillGLWindow() ;Kill Our Current Window
;   fullscreen=~fullscreen & 1 ;Toggle Fullscreen / Windowed Mode
;   ;Recreate Our OpenGL Window
;   If CreateGLWindow("NeHe's Collision Detection Tutorial",640,480,16,fullscreen)=0
;    ProcedureReturn 0 ;Quit If Window Was Not Created
;   EndIf
;  EndIf
 
EndProcedure

Procedure.b CreateGLWindow2(title.s,width.l,height.l,bits.l,fullscreenflag.b)

 Protected PixelFormat.l ;Holds The Results After Searching For A Match
 Protected wc.WNDCLASS ;Windows Class Structure
 Protected dwExStyle.l ;Window Extended Style
 Protected dwStyle.l ;Window Style
 Protected WindowRect.RECT ;Grabs Rectangle Upper Left / Lower Right Values
 Protected wpos.POINT ;Window position
 
 WindowRect\left=0 ;Set Left Value To 0
 WindowRect\right=width ;Set Right Value To Requested Width
 WindowRect\top=0 ;Set Top Value To 0
 WindowRect\bottom=height ;Set Bottom Value To Requested Height
 
 fullscreen=fullscreenflag ;Set The Global Fullscreen Flag
 
 hInstance=GetModuleHandle_(#Null) ;Grab An Instance For Our Window
 
 wc\style=#CS_HREDRAW | #CS_VREDRAW | #CS_OWNDC ;Redraw On Size, And Own DC For Window
 wc\lpfnWndProc=@WndProc() ;WndProc Handles Messages
 wc\cbClsExtra=0 ;No Extra Window Data
 wc\cbWndExtra=0 ;No Extra Window Data
 wc\hInstance=hInstance ;Set The Instance
 wc\hIcon=LoadIcon_(#Null,#IDI_WINLOGO) ;Load The Default Icon
 wc\hCursor=LoadCursor_(#Null,#IDC_ARROW) ;Load The Arrow Pointer
 wc\hbrBackground=#Null ;No Background Required For GL
 wc\lpszMenuName=#Null ;We Don't Want A Menu
 wc\lpszClassName=@"OpenGL" ;Set The Class Name 
 
 If RegisterClass_(wc)=0 ;Attempt To Register The Window Class
  MessageBox_(#Null,"Failed To Register The Window Class.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 EnumDisplaySettings_(#Null,#ENUM_CURRENT_SETTINGS,DMsaved) ;Save The Current Display State
 
 If fullscreen ;Attempt Fullscreen Mode?
 
  Protected dmScreenSettings.DEVMODE ;Device Mode
  dmScreenSettings\dmSize=SizeOf(DEVMODE) ;Size Of The Devmode Structure
  dmScreenSettings\dmFields=#DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT ;bit flags to specify the members of DEVMODE that were initialized
  dmScreenSettings\dmBitsPerPel=bits ;Selected Bits Per Pixel
  dmScreenSettings\dmPelsWidth=width ;Selected Screen Width in pixels
  dmScreenSettings\dmPelsHeight=height ;Selected Screen Height in pixels
 
  ;Try To Set Selected Mode And Get Results. Note: CDS_FULLSCREEN Gets Rid Of Start Bar
  If ChangeDisplaySettings_(dmScreenSettings,#CDS_FULLSCREEN)<>#DISP_CHANGE_SUCCESSFUL
   ;If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode
   If MessageBox_(#Null,"The Requested Fullscreen Mode Is Not Supported By"+Chr(10)+"Your Video Card. Use Windowed Mode Instead?","NeHe GL",#MB_YESNO | #MB_ICONEXCLAMATION)=#IDYES
    fullscreen=#False ;Windowed Mode Selected.  Fullscreen = FALSE
   Else
    ;Pop Up A Message Box Letting User Know The Program Is Closing
    MessageBox_(#Null,"Program Will Now Close.","ERROR",#MB_OK | #MB_ICONSTOP)
    ProcedureReturn #False
   EndIf
  EndIf
 
 EndIf
 
 If fullscreen ;Are We Still In Fullscreen Mode?
  dwExStyle=#WS_EX_APPWINDOW ;Window Extended Style
  dwStyle=#WS_POPUP ;Windows Style
  ShowCursor_(#False) ;Hide Mouse Pointer
 Else
  dwExStyle=#WS_EX_APPWINDOW | #WS_EX_WINDOWEDGE ;Window Extended Style
  dwStyle=#WS_OVERLAPPEDWINDOW ;Windows Style
 EndIf
 
 AdjustWindowRectEx_(WindowRect,dwStyle,#False,dwExStyle) ;Adjust Window To True Requested Size
 
 If fullscreen=0 ;if not fullscreen mode calculate screen centered window
  wpos\x=(GetSystemMetrics_(#SM_CXSCREEN)/2)-((WindowRect\right-WindowRect\left)/2)
  wpos\y=(GetSystemMetrics_(#SM_CYSCREEN)/2)-((WindowRect\bottom-WindowRect\top)/2)
 EndIf
 
 ;CreateWindowEx_(Extended Window Style, Class Name, Window Title, Window Style, Window X Position, Window Y Position, Width, Height, No Parent Window, No Menu, Instance, No Creation Data)
 hWnd=CreateWindowEx_(dwExStyle,"OpenGL",title,dwStyle | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN,wpos\x,wpos\y,WindowRect\right-WindowRect\left,WindowRect\bottom-WindowRect\top,#Null,#Null,hInstance,#Null)
 If hWnd=0
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Window Creation Error.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 Protected pfd.PIXELFORMATDESCRIPTOR ;pfd Tells Windows How We Want Things To Be
 pfd\nSize=SizeOf(PIXELFORMATDESCRIPTOR) ;Size Of This Structure
 pfd\nVersion=1 ;Version Number
 pfd\dwFlags=#PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW ;Format Must Support Window, OpenGL, Double Buffering
 pfd\iPixelType=#PFD_TYPE_RGBA ;Request An RGBA Format
 pfd\cColorBits=bits ;Select Our Color Depth
 pfd\cRedBits=0 ;Color Bits Ignored
 pfd\cRedShift=0
 pfd\cGreenBits=0
 pfd\cGreenShift=0
 pfd\cBlueBits=0
 pfd\cBlueShift=0
 pfd\cAlphaBits=0 ;No Alpha Buffer
 pfd\cAlphaShift=0 ;Shift Bit Ignored
 pfd\cAccumBits=0 ;No Accumulation Buffer
 pfd\cAccumRedBits=0 ;Accumulation Bits Ignored
 pfd\cAccumGreenBits=0
 pfd\cAccumBlueBits=0
 pfd\cAccumAlphaBits=0
 pfd\cDepthBits=16 ;16Bit Z-Buffer (Depth Buffer)
 pfd\cStencilBits=0 ;No Stencil Buffer
 pfd\cAuxBuffers=0 ;No Auxiliary Buffer
 pfd\iLayerType=#PFD_MAIN_PLANE ;Main Drawing Layer
 pfd\bReserved=0 ;Reserved
 pfd\dwLayerMask=0 ;Layer Masks Ignored
 pfd\dwVisibleMask=0
 pfd\dwDamageMask=0
 
 hDC=GetDC_(hWnd)
 If hDC=0 ;Did We Get A Device Context?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Create A GL Device Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 PixelFormat=ChoosePixelFormat_(hDC,pfd)
 If PixelFormat=0 ;Did Windows Find A Matching Pixel Format?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Find A Suitable PixelFormat.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 If SetPixelFormat_(hDC,PixelFormat,pfd)=0 ;Are We Able To Set The Pixel Format?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Set The PixelFormat.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 hRC=wglCreateContext_(hDC)
 If hRC=0 ;Are We Able To Get A Rendering Context?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Create A GL Rendering Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 If wglMakeCurrent_(hDC,hRC)=0 ;Try To Activate The Rendering Context
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Activate The GL Rendering Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 ShowWindow_(hWnd,#SW_SHOW) ;Show The Window
 SetForegroundWindow_(hWnd) ;Slightly Higher Priority
 SetFocus_(hWnd) ;Sets Keyboard Focus To The Window
 ReSizeGLScene(width,height) ;Set Up Our Perspective GL Screen
 
 If InitGL()=0 ;Initialize Our Newly Created GL Window
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Initialization Failed.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 ProcedureReturn #True ;Success
 
EndProcedure

; Procedure.l WinMain() ;Main Program
; ExamineDesktops()
;  width.l = DesktopWidth(0)
;  height.l= DesktopHeight(0)
;  depth.l = DesktopDepth(0)
;  Protected msg.MSG ;Windows Message Structure
;  Protected done.b ;Bool Variable To Exit Loop
;  
; ;Ask The User Which Screen Mode They Prefer
; If MessageBox_(#Null,"Would You Like To Run In Fullscreen Mode?","Start FullScreen?",#MB_YESNO | #MB_ICONQUESTION)=#IDNO
;  fullscreen=#False ;Windowed Mode
; EndIf
;  
;  InitVars() ;Initialize Variables
;  
;  
;  If CreateGLWindow("NeHe's Collision Detection Tutorial",width,height,depth,fullscreen)=0 ;Create The Window
;   ProcedureReturn 0 ;Quit If Window Was Not Created
;  EndIf
;  ;colorballs()
;  
;  While done=#False ;Loop That Runs While done=FALSE
;  
;   If PeekMessage_(msg,#Null,0,0,#PM_REMOVE) ;Is There A Message Waiting?
;  
;    If msg\message=#WM_QUIT ;Have We Received A Quit Message?
;     done=#True ;If So done=TRUE
;    Else ;If Not, Deal With Window Messages
;     TranslateMessage_(msg) ;Translate The Message
;     DispatchMessage_(msg) ;Dispatch The Message
;    EndIf
;    
;   Else ;If There Are No Messages
;  
;    If active
;    
;     ;Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
;     If keys(#VK_ESCAPE) ;Active?  Was There A Quit Received?
;    
;      done=#True ;ESC or DrawGLScene Signalled A Quit
;      
;     Else ;Not Time To Quit, Update Screen
;    
; ;      idle() ;Advance Simulation
; ;      DrawGLScene() ;Draw Scene
; ;      SwapBuffers_(hDC) ;Swap Buffers (Double Buffering)
; ;      ProcessKeys() ;Process Key Presses
;      
;     EndIf
;    
;    EndIf
;    
;   EndIf
;  
;  Wend
;  
;  ;Shutdown
;  KillGLWindow() ;Kill The Window
;  glDeleteTextures_(4,gltexture()) ;Free textures
;  End ;Exit The Program
;  
; EndProcedure

;XIncludeFile "OpenGlEngineTest.pb"
; IDE Options = PureBasic 4.51 (Windows - x86)

; CursorPosition = 360
; FirstLine = 334
; Folding = -----


; EnableAsm
; UseMainFile = ..\space invaders\SpaceInvadersMain.pb
; Executable = F:\SpaceInvaders.exe
; DisableDebugger
; IDE Options = PureBasic 4.51 (Windows - x86)
; CursorPosition = 394
; Folding = ----
; EnableXP